package com.szcinda.service.rate;

import com.szcinda.repository.*;
import com.szcinda.service.SnowFlakeFactory;
import com.szcinda.service.dto.log.LogCreateDto;
import com.szcinda.service.dto.log.LogService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
public class RateServiceImpl implements RateService {

    private final RateRepository rateRepository;
    private final SnowFlakeFactory snowFlakeFactory;
    private final UserRepository userRepository;
    private final ClientRepository clientRepository;
    private final CarrierRepository carrierRepository;
    private final LogService logService;

    public RateServiceImpl(RateRepository rateRepository, UserRepository userRepository,
                           ClientRepository clientRepository, CarrierRepository carrierRepository, LogService logService) {
        this.rateRepository = rateRepository;
        this.userRepository = userRepository;
        this.clientRepository = clientRepository;
        this.carrierRepository = carrierRepository;
        this.logService = logService;
        this.snowFlakeFactory = SnowFlakeFactory.getInstance();
    }

    @Override
    public void createCommon(RateCreateDto createDto) {
        /*List<ExchangeRate> exchangeRates = rateRepository.findAll();*/
        /*ExchangeRate exchangeRate = exchangeRates.stream().filter(rate -> (rate.getFromRate().equals(createDto.getFromRate()) || rate.getFromRate().equals(createDto.getToRate())) &&
                (rate.getToRate().equals(createDto.getFromRate()) || rate.getToRate().equals(createDto.getToRate())))
                .findFirst().orElse(null);
        Assert.isTrue(exchangeRate == null, "存在此汇率的相互转换记录");*/
        ExchangeRate exchangeRate = new ExchangeRate();
        BeanUtils.copyProperties(createDto, exchangeRate);
        exchangeRate.setId(snowFlakeFactory.nextId("ER"));
        rateRepository.save(exchangeRate);
        User user = userRepository.findById(createDto.getOpId());
        LogCreateDto logCreateDto = new LogCreateDto(user.getId(), user.getNickName(), "新增汇率", exchangeRate.getFromRate() + "-" + exchangeRate.getToRate());
        logService.create(logCreateDto);
    }

    @Override
    public void updateClientRate(ClientRateUpdateDto updateDto) {
        String name;
        Client client = clientRepository.findById(updateDto.getBelongId());
        if (client != null) {
            name = client.getName();
        } else {
            Carrier carrier = carrierRepository.findById(updateDto.getBelongId());
            name = carrier.getName();
        }
        rateRepository.deleteAllByBelongId(updateDto.getBelongId());
        List<ExchangeRate> rates = new ArrayList<>();
        updateDto.getRates().forEach(dto -> {
            ExchangeRate create = new ExchangeRate();
            BeanUtils.copyProperties(dto, create);
            create.setId(snowFlakeFactory.nextId("ER"));
            create.setBelongId(updateDto.getBelongId());
            rates.add(create);
        });
        rateRepository.save(rates);
    }

    @Override
    public void update(RateUpdateDto updateDto) {
        ExchangeRate rate = rateRepository.findById(updateDto.getId());
        rate.setRate(updateDto.getRate());
        rate.setStartDate(updateDto.getStartDate());
        rate.setEndDate(updateDto.getEndDate());
        rateRepository.save(rate);
        User user = userRepository.findById(updateDto.getOpId());
        LogCreateDto logCreateDto = new LogCreateDto(user.getId(), user.getNickName(), "修改汇率", rate.getFromRate() + "-" + rate.getToRate());
        logService.create(logCreateDto);
    }

    @Override
    public List<ExchangeRate> getCommon() {
        return rateRepository.findByBelongIdIsNullOrderByCreateTimeDesc();
    }

    @Override
    public void delete(String id, String userId) {
        ExchangeRate rate = rateRepository.findById(id);
        rateRepository.delete(rate);
        User user = userRepository.findById(userId);
        LogCreateDto logCreateDto = new LogCreateDto(user.getId(), user.getNickName(), "删除汇率", rate.getFromRate() + "-" + rate.getToRate());
        logService.create(logCreateDto);
    }

    @Override
    public List<ExchangeRate> getAll() {
        return this.getCanUseRate();
    }

    @Override
    public List<RateCurrencyDto> getCurrency() {
        List<ExchangeRate> rates = rateRepository.findByBelongIdIsNullOrderByCreateTimeDesc();
        List<RateCurrencyDto> currencyDtos = new ArrayList<>();
        rates.forEach(exchangeRate -> {
            String fromRate = exchangeRate.getFromRate();
            String toRate = exchangeRate.getToRate();
            boolean present = currencyDtos.stream().anyMatch(dto -> dto.getName().equals(fromRate));
            if (!present) {
                currencyDtos.add(new RateCurrencyDto(exchangeRate.getFromRate(), exchangeRate.getFromRate()));
            }
            present = currencyDtos.stream().anyMatch(dto -> dto.getName().equals(toRate));
            if (!present) {
                currencyDtos.add(new RateCurrencyDto(exchangeRate.getToRate(), exchangeRate.getToRate()));
            }
        });
        return currencyDtos;
    }

    @Override
    public List<ExchangeRate> getCanUseRate() {
        List<ExchangeRate> rates = new ArrayList<>();
        List<ExchangeRate> exchangeRates = rateRepository.findAll();
        LocalDate now = LocalDate.now();
        for (ExchangeRate exchangeRate : exchangeRates) {
            if (exchangeRate.getStartDate() != null && exchangeRate.getEndDate() != null) {
                if (now.isAfter(exchangeRate.getStartDate().minusDays(1)) && now.isBefore(exchangeRate.getEndDate().plusDays(1))) {
                    // 符合条件的一条记录
                    boolean anyMatch = rates.stream().anyMatch(rate -> (rate.getFromRate().equals(exchangeRate.getFromRate()) || rate.getFromRate().equals(exchangeRate.getToRate())) &&
                            (rate.getToRate().equals(exchangeRate.getFromRate()) || rate.getToRate().equals(exchangeRate.getToRate())));
                    if (!anyMatch) {
                        rates.add(exchangeRate);
                    }
                }
            }
        }
        return rates;
    }
}
